use std::any::Any;

use crate::id::Id;
use crate::message::EventResult;
use crate::sequence::ViewMarker;
use crate::view::{Cx, View};
use crate::widget;
use crate::widget::ChangeFlags;

pub struct Button<T, A> {
    text: String,
    f: fn(&mut T) -> A,
}

impl<T, A> ViewMarker for Button<T, A> {}

impl<T, A> Button<T, A> {
    pub fn new(text: String, f: fn(&mut T) -> A) -> Self {
        Self { text, f }
    }
}

impl<T, A> View<T, A> for Button<T, A> {
    type State = ();
    type Element = widget::Button;

    fn build(&self, cx: &mut Cx) -> (Id, Self::State, Self::Element) {
        let (id, element) =
            cx.with_new_id(|cx| widget::Button::new(self.text.clone(), cx.id_path.clone()));
        (id, (), element)
    }

    fn rebuild(
        &self,
        prev: &Self,
        _cx: &mut Cx,
        _id: &mut Id,
        _state: &mut Self::State,
        element: &mut Self::Element,
    ) -> ChangeFlags {
        if self.text != prev.text {
            element.text = self.text.clone();
            ChangeFlags::LAYOUT | ChangeFlags::PAINT
        } else {
            ChangeFlags::empty()
        }
    }

    fn message(
        &self,
        _id_path: &[Id],
        _state: &mut Self::State,
        _event: Box<dyn Any>,
        app_state: &mut T,
    ) -> EventResult<A> {
        EventResult::Action((self.f)(app_state))
    }
}
